#include "utilities.h"

//Contains the code for notify and check messages
void notifyProcessing(msg_header msgRespHdr, listBuffStruct eventReq)
{
	map<int,writeListData>::iterator it;
	list<fromUOIDStr>::iterator itF;
	//This code includes the notify request processing
	if((uint8_t)msgRespHdr.msgtype == 0xF7)
	{
		if(printFlag==1)
		{
			cout<<"Got notify msg from - "<<eventReq.portNumber<<endl;
		}
		//Now delete the port from the myMap so that its socket is completely destroyed if not destroyed.
		pthread_mutex_lock(&maplock);
		if(myMap.find(eventReq.portNumber) != myMap.end())
		{
			close(myMap.find(eventReq.portNumber)->second.socknumber);
		}
		pthread_mutex_unlock(&maplock);
		pthread_mutex_lock(&writeMapMutex);
		writeListData listDataStr = writeMap[eventReq.portNumber];
		listDataStr.dieflag = true;
		writeMap[eventReq.portNumber] = listDataStr;
		pthread_mutex_unlock(&writeMapMutex);
		//Send a Check request to neighbors to see if connected to the core network.
		if(!isBeacon)
		{
			msg_header chkHdr;
			char obj[256];
			strcpy(obj, "CKRQ");
			createMsgHdrStr(&chkHdr,0xF6,1,obj,node_instance_id,0);
			listBuffStruct lbtemp;
			lbtemp.datalength = 27;
			memset(lbtemp.listBuff, '\0', 27);
			fillMsgHdrBuffer(chkHdr, lbtemp.listBuff);
			pthread_mutex_lock(&writeMapMutex);
			for(it=writeMap.begin(); it!=writeMap.end(); it++)
			{
				if((*it).first!=eventReq.portNumber)
				{
					if(printFlag==1)
					{
						cout<<"chk req sending to "<<(*it).first<<endl;
					}
					lbtemp.portNumber = (*it).first;
					writeListData listDataStr = writeMap[(*it).first];
					listDataStr.response.push_back(lbtemp);
					writeMap[(*it).first] = listDataStr;
				}
			}
			pthread_mutex_unlock(&writeMapMutex);
			struct timeval chkTime;
			gettimeofday(&chkTime,NULL);
			checkResponseTime = (double)(chkTime.tv_sec * 1000 + (double)chkTime.tv_usec/1000);
		}
	}
	//This is the code for check request processing
	if((uint8_t)msgRespHdr.msgtype == 0xF6)
	{
		if(printFlag==1)
		{
			cout<<"Got chk request msg from - "<<eventReq.portNumber<<endl;
		}
		if(isBeacon)
		{
			//make response and send it to the node where the requet came from
			int testUOID = findInUOIDList(msgRespHdr.uoid);
			if(testUOID == 1)
			{
			
			}
			else
			{
			uoidStr tempUOIDStr;
			struct timeval time1;
			gettimeofday(&time1, NULL);
			tempUOIDStr.timeOfTheDay = (double)(time1.tv_sec * 1000 + (double)time1.tv_usec/1000);
			tempUOIDStr.msgLifeTime = initMap["MsgLifetime"];
			memcpy(tempUOIDStr.msgUOID, msgRespHdr.uoid, 20);
			pthread_mutex_lock(&uoidlock);
			myUOIDList.push_back(tempUOIDStr);
			pthread_mutex_unlock(&uoidlock);
			msg_header chkHdr;
			char obj[256];
			strcpy(obj, "CKRS");
			createMsgHdrStr(&chkHdr,0xF5,1,obj,node_instance_id,20);
			listBuffStruct lbtemp;
			memset(lbtemp.listBuff, '\0', 47);
			fillMsgHdrBuffer(chkHdr, lbtemp.listBuff);
			memcpy(&(lbtemp.listBuff[27]),msgRespHdr.uoid,20);
			lbtemp.datalength = 47;
			lbtemp.portNumber = eventReq.portNumber;
			pthread_mutex_lock(&writeMapMutex);
			writeListData listDataStr = writeMap[eventReq.portNumber];
			listDataStr.response.push_back(lbtemp);
			writeMap[eventReq.portNumber] = listDataStr;
			pthread_mutex_unlock(&writeMapMutex);
			}
		}
		else
		{
			//a non beacon forwards to the other neighbors
			int testUOID = findInUOIDList(msgRespHdr.uoid);
			if(testUOID == 1)
			{
			
			}
			else
			{
				uoidStr tempUOIDStr;
				struct timeval time1;
				gettimeofday(&time1, NULL);
				tempUOIDStr.timeOfTheDay = (double)(time1.tv_sec * 1000 + (double)time1.tv_usec/1000);
				tempUOIDStr.msgLifeTime = initMap["MsgLifetime"];
				memcpy(tempUOIDStr.msgUOID, msgRespHdr.uoid, 20);
				pthread_mutex_lock(&uoidlock);
				myUOIDList.push_back(tempUOIDStr);
				pthread_mutex_unlock(&uoidlock);
				listBuffStruct lbtemp;
				lbtemp.logtype=2;
				int tempTTL = msgRespHdr.timetolive;
				tempTTL--;
				msgRespHdr.timetolive = tempTTL;
				memset(&lbtemp.listBuff, '\0', 27);
				fillMsgHdrBuffer(msgRespHdr, lbtemp.listBuff);
				lbtemp.datalength = 27;
				pthread_mutex_lock(&writeMapMutex);
				for(it=writeMap.begin(); it!=writeMap.end(); it++)
				{
					if((*it).first!=eventReq.portNumber)
					{
						//store the uoid in a map so that when it recieves a response then send it to the persone who initiated it.
						fromUOIDStr fromTemp;
						memcpy(fromTemp.uoid, &msgRespHdr.uoid, 20);
						fromTemp.portnumber = eventReq.portNumber;
						myFromUOIDList.push_back(fromTemp);
						lbtemp.portNumber = (*it).first;
						writeListData listDataStr = writeMap[(*it).first];
						listDataStr.response.push_back(lbtemp);
						writeMap[(*it).first] = listDataStr;
					}
				}
				pthread_mutex_unlock(&writeMapMutex);
			}
			
			}
		
	
	}
	//This is the part where the response of check is dealt with
	if((uint8_t)msgRespHdr.msgtype == 0xF5)
	{
		if(printFlag==1)
		{
			cout<<"Got check response msg from - "<<eventReq.portNumber<<endl;
		}	
		int testUOID = findInUOIDList(msgRespHdr.uoid);
		if(testUOID == 1)
		{
			
		}
		else
		{
			if(checkResponseTime!=-1)
			{
				checkResponseTime = -1;
			}
			else
			{
				//Forward the response onto the path where the request originated.
				int tempTTL = msgRespHdr.timetolive;
				if(printFlag==1)
				{
					cout<<"TTL - "<<tempTTL<<endl;
				}
				tempTTL--;
				listBuffStruct lbtemp;
				uoidStr tempUOIDStr;
				struct timeval time1;
				gettimeofday(&time1, NULL);
				tempUOIDStr.timeOfTheDay = (double)(time1.tv_sec * 1000 + (double)time1.tv_usec/1000);
				tempUOIDStr.msgLifeTime = initMap["MsgLifetime"];
				memcpy(tempUOIDStr.msgUOID, msgRespHdr.uoid, 20);
				pthread_mutex_lock(&uoidlock);
				myUOIDList.push_back(tempUOIDStr);
				pthread_mutex_unlock(&uoidlock);
				memset(&lbtemp.listBuff, '\0', eventReq.datalength);
				fillMsgHdrBuffer(msgRespHdr, lbtemp.listBuff);
				lbtemp.datalength = eventReq.datalength;
				lbtemp.portNumber = eventReq.portNumber;
				lbtemp.logtype=2;
				memcpy(&(lbtemp.listBuff[27]),&(eventReq.listBuff[27]),20);
				pthread_mutex_lock(&writeMapMutex);
				for(itF=myFromUOIDList.begin(); itF!=myFromUOIDList.end(); itF++)
				{
					fromUOIDStr temp = *itF;
					if(memcmp(&(eventReq.listBuff[27]),temp.uoid,20)==0)
					{
						writeListData listDataStr = writeMap[temp.portnumber];
						listDataStr.response.push_back(lbtemp);
						writeMap[temp.portnumber] = listDataStr;
						break;
					}
				}
				pthread_mutex_unlock(&writeMapMutex);
		
			}
		}	
	}
}
